package com.jar.exercise.jvm操作.类加载器;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 自定义类加载器，加载指定路径的字节码文件，也可以实现自己的编解码规则
 * 1、新建自定义类，继承ClassLoader，重写findClass方法
 * <p>
 * 2、将字节码文件转成Class类的实例
 * <p>
 * 3、调用classLoad方法即可
 */
public class MyClassLoad extends ClassLoader {
    private String path;

    public MyClassLoad(String path) {
        this.path = path;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class<?> aClass = null;
        byte[] classData = getData();
        if (classData != null) {
            // 将class的字节码数组转换成Class类的实例
            aClass = defineClass(name, classData, 0, classData.length);
        }
        return aClass;
    }

    private byte[] getData() {
        File file = new File(path);
        if (file.exists()) {
            FileInputStream in = null;
            ByteArrayOutputStream out = null;
            try {
                in = new FileInputStream(file);
                out = new ByteArrayOutputStream();

                byte[] buffer = new byte[1024];
                int size = 0;
                while ((size = in.read(buffer)) != -1) {
                    out.write(buffer, 0, size);
                }

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                } catch (IOException e) {

                    e.printStackTrace();
                }
            }
            return out.toByteArray();
        } else {
            return null;
        }


    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        String path = "D:\\ClassLoadTest.class";
        String classFullName = "com.jar.exercise.jvm操作.类加载器.ClassLoadTest";
        MyClassLoad myClassLoad = new MyClassLoad(path);
        Class<?> loadClass = myClassLoad.findClass(classFullName);
        System.out.println("类加载器是：" + loadClass.getClassLoader());

        Method main = loadClass.getDeclaredMethod("main", String[].class);
        String[] arg = {"ag"};
        Object o = loadClass.newInstance();
        main.invoke(o, (Object) arg);
    }
}
